package com.example.springboot.config;

import ch.qos.logback.classic.db.DBHelper;
import com.example.springboot.bean.Car;
import com.example.springboot.bean.Person;
import com.example.springboot.bean.Pet;
import com.example.springboot.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

/**
 * 1.配置类里面使用 @Bean标注在方法上给容器注册组件，
 *      默认也是单实例(创建一次 即 即使在new 也是同一个)的
 * 2.配置类本身也是组件
 * 3.@Configuratio()   proxyBeanMethods:
 *            是不是代理bean的方法(代理说明得这个类操作 单实例的)
 *       Full(proxyBeanMethods = true)//单实例   默认  每次都先判断有没有创建过组件
 *       Lite(proxyBeanMethods = false)//多实例
 *
 * @Configuration(proxyBeanMethods = true)//代理对象调用方法（默认的）
 *        SpringBoot总会检查这个组件是否在容器中有  保持单实例
 * @Configuration(proxyBeanMethods = false)   不保持单实例
 *     这是一个配置类 == 配置文件告诉spring boot这是一个配置类
 *
 * 最佳实战    如果有依赖  最好是true(单实例 每次使用都会查询内部有没有)
 *            如果没依赖  最好是false  这样少了一次遍历所有组件的时间  效率高
 *     配置类组件之间无依赖关系用Lite模式加速容器启动过程,减少判断
 *     配置类组件之间有依赖关系,方法会被调用得到之前单实例组件,用Full模式
 *
 *
 * 4.@Import({User.class})
 *      给容器中自动创建出这个类型的组件   默认组建的名称就是"全类名"
 *
 * @EnableConfigurationProperties({Car.class,Person.class})
 * //1.开启Car的配置绑定功能
 * //2.把这个Car的个组件自动注册到容器中
 *
 */
@Import({User.class, DBHelper.class})//给容器中自动创建出这个类型的组件
@Configuration//(proxyBeanMethods = false)//这是一个配置类 == 配置文件告诉spring boot这是一个配置类 主要
//@ImportResource("classpath:beans.xml")//将 .xml 里的组件导入
@EnableConfigurationProperties({Car.class,Person.class}) //
//1.开启Car的配置绑定功能//2.把这个Car的个组件自动注册到容器中
public class MyConfig_1 {

    /**
     * @ConditionalOnClass() //存在()内这个类才加载
     * @ConditionalOnMissingClass() //不存在存在()内这个类才加载
     */
    @ConditionalOnMissingBean(name = "pet001")//当没有tom这个组件才加载这个组件
//    @ConditionalOnBean(name = "pet001")//当有pet001这个组件时  才加载这个组件
    //（如果pet01在后面 仍然不加载）   因为在准备加载这个组件时   pet001组件没有加载
    @Bean//给容器中添加组件。以方法名作为组件的id。返回类型就是组件类型。返回的值，就是组件在容器中的实例
    public User user001(){
        User user = new User("张三", 18);
        user.setPet(pet001());
        return user;
    }

    @Bean("pet001")//默认组件名字为方法名   也可以自定义组件名字("pet01")
    public Pet pet001(){
        return new Pet("小狗",15.5);
    }



}
